package com.laf.manage.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.laf.common.constant.CacheConstants;
import com.laf.common.core.domain.model.LoginMobileUser;
import com.laf.common.core.redis.RedisCache;
import com.laf.common.exception.ServiceException;
import com.laf.common.utils.SecurityUtils;
import com.laf.manage.constant.LostItemStatusConstant;
import com.laf.manage.domain.dto.PageDTO;
import com.laf.manage.domain.dto.StoreDTO;
import com.laf.manage.domain.po.Dynamic;
import com.laf.manage.domain.po.LostItem;
import com.laf.manage.domain.po.Store;
import com.laf.manage.domain.query.StoreQuery;
import com.laf.manage.domain.vo.StoreVO;
import com.laf.manage.enums.ContentTypeEnum;
import com.laf.manage.enums.VerifyStatusEnum;
import com.laf.manage.mapper.mp.StoreMapper;
import com.laf.manage.service.IDynamicService;
import com.laf.manage.service.ILostItemService;
import com.laf.manage.service.IStoreService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 收藏表 服务实现类
 * </p>
 *
 * @author zian
 * @since 2024-11-10
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements IStoreService {

    private final ILostItemService lostItemService;

    private final IDynamicService dynamicService;

    private final RedisCache redisCache;

    /**
     * 添加收藏
     *
     * @param dto contentId : 内容id
     *            contentType : 内容类型
     */
    @Override
    public void addStore(StoreDTO dto) {
        Long contentId = dto.getContentId();
        Integer contentType = dto.getContentType();

        // 校验要添加的收藏参数
        checkParams(contentType, contentId);

        LoginMobileUser mobileLoginUser = SecurityUtils.getMobileLoginUser();

        // 判断用户是否收藏过该内容了 ，如果收藏过了，直接跳过即可
        Store one = lambdaQuery()
                .eq(Store::getContentId, contentId)
                .eq(Store::getContentType, contentType)
                .eq(Store::getCreateUserId, mobileLoginUser.getUserId())
                .one();
        if (one != null) return;


        // 封装po ，存储的mysql 中
        Store store = new Store();
        store.setContentId(contentId);
        store.setContentType(ContentTypeEnum.getEnumByCode(contentType));
        store.setCreateUserId(mobileLoginUser.getUserId());
        store.setUpdateBy(mobileLoginUser.getUsername());
        store.setCreateBy(mobileLoginUser.getUsername());
        boolean b = save(store);
        if (!b) throw new ServiceException("添加收藏失败");

        // 判断缓存中动态对应的收藏数据
        if (dto.getContentType().equals(ContentTypeEnum.DYNAMIC.getCode())) {
            Object cacheMapValue = redisCache.getCacheMapValue(CacheConstants.STORE_PREFIX, dto.getContentId().toString());
            if (cacheMapValue != null) {
                redisCache.setCacheMapValue(CacheConstants.STORE_PREFIX, dto.getContentId().toString(), (Integer) cacheMapValue + 1);
            } else {
                redisCache.setCacheMapValue(CacheConstants.STORE_PREFIX, dto.getContentId().toString(), 1);
            }
        }

    }

    /**
     * 当前登录用户的收藏
     *
     * @param id 收藏id
     */
    @Override
    public void deleteStoreById(Long id) {

        // 判断收藏记录是否存在
        Long userId = SecurityUtils.getMobileUserId();
        Store one = lambdaQuery()
                .eq(Store::getId, id)
                .eq(Store::getCreateUserId, userId)
                .one();
        if (one == null) throw new ServiceException("收藏不存在");

        // 删除收藏记录
        boolean b = removeById(id);
        if (!b) throw new ServiceException("删除失败");

        // 删除缓存
        // redisCache.deleteCacheMapValue(CacheConstants.STORE_PREFIX, one.getContentId().toString());
        // 重新缓存收藏数
        if (one.getContentType().equals(ContentTypeEnum.DYNAMIC)) {
            Integer dynamicStoreCountByDynamicId = getBaseMapper().dynamicStoreCountByDynamicId(one.getContentId());
            redisCache.setCacheMapValue(CacheConstants.STORE_PREFIX, one.getContentId().toString(), dynamicStoreCountByDynamicId);
        }
    }

    /**
     * 查询当前用户的收藏列表
     *
     * @param query 条件
     * @return
     */
    @Override
    public PageDTO<StoreVO> selectStoreList(StoreQuery query) {
        Page<StoreVO> page = query.toMpPageDefaultSortByCreateTimeDesc();
        List<StoreVO> list = new ArrayList<>();
        // 封装分页参数
        if (ContentTypeEnum.DYNAMIC.getCode().equals(query.getContentType())) {
            // 查询动态收藏
            list = getBaseMapper().selectStoreDynamicList(page, query);
            // 补充其他数据
            setOtherData(list);
        } else if (ContentTypeEnum.LOST_ITEM.getCode().equals(query.getContentType())) {
            // 查询失物收藏
            list = getBaseMapper().selectStoreLostItemList(page, query);
        } else {
            throw new ServiceException("内容类型错误");
        }
        // 判断是否为空
        if (CollUtil.isEmpty(list)) {
            return PageDTO.empty(0L, 0L);
        }
        return PageDTO.of(page, list);
    }

    private void setOtherData(List<StoreVO> list) {
        list.forEach(item -> {
            // 获取缓存中动态对应的收藏数据
            item.setStoreCount(getCacheStore(item.getContentId()));
            // 获取缓存中评论数据
            item.setCommentCount(getCacheComment(item.getContentId()));
        });
    }

    private void checkParams(Integer contentType, Long contentId) {
        // 判断内容是否存在
        if (ContentTypeEnum.DYNAMIC.getCode().equals(contentType)) {
            // 查询动态表
            Dynamic dynamic = dynamicService.getById(contentId);
            if (dynamic == null) {
                throw new ServiceException("动态不存在");
            }

            // 只有通过审核的动态才可以收藏
            if (!dynamic.getVerifyStatus().equals(VerifyStatusEnum.VERIFY_PASS)) {
                throw new ServiceException("当前状态不允许收藏");
            }

        } else if (ContentTypeEnum.LOST_ITEM.getCode().equals(contentType)) {
            // 查询失物表
            LostItem lostItem = lostItemService.getById(contentId);
            if (lostItem == null) {
                throw new ServiceException("失物不存在");
            }

            // 只有待领取的才能收藏
            if (!lostItem.getStatus().equals(LostItemStatusConstant.WAIT_PICKED)) {
                throw new ServiceException("当前状态不允许收藏");
            }
        } else {
            throw new ServiceException("内容类型错误");
        }
    }


    /**
     * 获取缓存中浏览数量
     *
     * @param id dynamicId
     * @return 浏览数量
     */
    public Integer getCacheHits(Long id) {
        Object cacheMapValue = redisCache.getCacheMapValue(CacheConstants.HITS_PREFIX, id.toString());
        if (cacheMapValue != null) {
            return (Integer) cacheMapValue;
        }
        return 0;
    }


    /**
     * 获取缓存中收藏数量
     *
     * @param id dynamicId
     * @return 收藏数量
     */
    public Integer getCacheStore(Long id) {
        Object cacheMapValue = redisCache.getCacheMapValue(CacheConstants.STORE_PREFIX, id.toString());
        if (cacheMapValue != null) {
            return (Integer) cacheMapValue;
        }
        return 0;
    }


    /**
     * 获取缓存中评论数量
     *
     * @param id dynamicId
     * @return 评论数
     */
    public Integer getCacheComment(Long id) {
        Object cacheMapValue = redisCache.getCacheMapValue(CacheConstants.COMMENTS_PREFIX, id.toString());
        if (cacheMapValue != null) {
            return (Integer) cacheMapValue;
        }
        return 0;
    }


}
